package org.university.service.impl;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.university.common.ApiResponse;
import org.university.entity.Enrollment;
import org.university.entity.Student;
import org.university.entity.TeachingClass;
import org.university.enums.GlobalEnums;
import org.university.repository.EnrollmentRepository;
import org.university.repository.StudentRepository;
import org.university.repository.TeachingClassRepository;
import org.university.service.EnrollmentService;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.NoSuchElementException;

@Service
public class EnrollmentServiceImpl extends GenericServiceImpl<Enrollment, Integer> implements EnrollmentService {

    private final StudentRepository studentRepository;
    private final EnrollmentRepository enrollmentRepository;
    private final TeachingClassRepository teachingClassRepository;

    public EnrollmentServiceImpl(EnrollmentRepository enrollmentRepository,
                                 StudentRepository studentRepository,
                                 TeachingClassRepository teachingClassRepository) {
        super(enrollmentRepository);
        this.enrollmentRepository = enrollmentRepository;
        this.studentRepository = studentRepository;
        this.teachingClassRepository = teachingClassRepository;
    }

    @Transactional
    @Override
    public Enrollment enrollStudent(String studentId, Integer classId) {
        // 查找学生
        Student student = studentRepository.findById(studentId)
                .orElseThrow(() -> new NoSuchElementException("学生不存在: " + studentId));

        // 查找教学班
        TeachingClass teachingClass = teachingClassRepository.findById(classId)
                .orElseThrow(() -> new NoSuchElementException("教学班不存在: " + classId));

        // 检查是否已达最大选课人数
        if (teachingClass.getCurrentStudents() >= teachingClass.getMaxStudents()) {
            throw new RuntimeException("该课程已达最大选课人数");
        }

        // 创建选课记录
        Enrollment enrollment = new Enrollment();

        // 获取当前 LocalDateTime
        LocalDateTime now = LocalDateTime.now();
        // 转换为 Date（需要先转为 Instant）
        Date date = Date.from(now.atZone(ZoneId.systemDefault()).toInstant());
        // 设置到对象中
        enrollment.setStudentId(student.getStudentId());
        // enrollment.setClassId(teachingClass.getClassId());   // 之前的写法
        enrollment.setTeachingClass(teachingClass);
        enrollment.setStatus(GlobalEnums.Status.已退);

        // 保存选课记录
        Enrollment savedEnrollment = enrollmentRepository.save(enrollment);

        // 更新教学班当前人数
        teachingClass.setCurrentStudents(teachingClass.getCurrentStudents() + 1);
        teachingClassRepository.save(teachingClass);

        return savedEnrollment;
    }

    @Transactional
    public ResponseEntity<ApiResponse<Enrollment>> selectCourse(String studentId, String courseId) {
        if (!studentRepository.existsById(studentId)) {
            throw new IllegalArgumentException("学生不存在: " + studentId);
        }

        // 1. 检查学生是否已选该课程
        if (isStudentEnrolledInCourse(studentId, courseId)) {
            // throw new RuntimeException("您已选修该课程，请勿重复选课");
            return ApiResponse.error(HttpStatus.BAD_REQUEST, "您已选修该课程，请勿重复选课");
        }

        // 检查是否有开设该课程的教学班
        Integer classCount = teachingClassRepository.isOffering(courseId);
        if (classCount == 0) {
            return ApiResponse.error(HttpStatus.BAD_REQUEST, "该课程未开设");
            // throw new RuntimeException("该课程未开设");
        }

        // 2. 查找可用的班级
        TeachingClass tc = teachingClassRepository.findAvailableClass(courseId)
                .orElseThrow(() -> new RuntimeException("无可用名额"));

        // 3. 创建选课记录
        Enrollment enrollment = new Enrollment();
        enrollment.setStudentId(studentId);
        // enrollment.setClassId(tc.getClassId());
        enrollment.setTeachingClass(tc);
        enrollment.setStatus(GlobalEnums.Status.valueOf("已选"));
        enrollment.setEnrollmentDate(LocalDate.now());

        // 4. 更新班级人数
        tc.setCurrentStudents(tc.getCurrentStudents() + 1);
        teachingClassRepository.save(tc);

        return ApiResponse.success(enrollmentRepository.save(enrollment));
    }

    // 检查学生是否已选该课程
    private boolean isStudentEnrolledInCourse(String studentId, String courseId) {
        return enrollmentRepository.existsByStudentIdAndCourseId(studentId, courseId);
    }

    @Transactional
    @Override
    public void dropCourse(Integer enrollmentId) {
        // 1. 查找选课记录
        Enrollment enrollment = enrollmentRepository.findById(enrollmentId)
                .orElseThrow(() -> new NoSuchElementException("选课记录不存在: " + enrollmentId));

        // 2. 检查是否已退课（避免重复操作）
        if (enrollment.getStatus() == GlobalEnums.Status.已退) {
            throw new IllegalStateException("该课程已退，无需重复操作");
        }

        // 3. 获取关联的教学班对象
        TeachingClass teachingClass = enrollment.getTeachingClass();
        if (teachingClass == null) {
            throw new IllegalStateException("关联的教学班不存在");
        }

        // 4. 更新选课状态
        enrollment.setStatus(GlobalEnums.Status.已退);
        enrollmentRepository.save(enrollment);

        // 5. 更新教学班当前人数（需确保不小于0）
        int newCount = teachingClass.getCurrentStudents() - 1;
        if (newCount < 0) {
            throw new IllegalStateException("教学班人数异常");
        }
        teachingClass.setCurrentStudents(newCount);
        teachingClassRepository.save(teachingClass);
    }

    @Override
    public Page<Enrollment> findAll(Pageable pageable) {
        return null;
    }
}
